﻿using DevelopTool.Common;
using DevelopTool.Forms.BaseForms;
using DevelopTool.Forms.CommonControls;
using DevelopTool.Model;
using DevelopTool.Model.CommonModels;
using DevelopTool.Model.Enums;
using Sunny.UI;
using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Windows.Forms;

namespace DevelopTool.Forms.FolderToolForms
{
    /// <summary>
    /// 目录监控
    /// </summary>
    public partial class FolderWatcherForm : BaseUIPage
    {
        private string folderPath;

        /// <summary>
        /// 目录路径
        /// </summary>
        public string FolderPath
        {
            get
            {
                return this.folderPath;
            }
            set
            {
                this.folderPath = value;
            }
        }

        private FileSystemWatcher fileSystemWatcher;

        /// <summary>
        /// 结果
        /// </summary>
        private DataTable resultTable;

        /// <summary>
        /// DataGridView列信息集合
        /// </summary>
        private List<DataGridColumn> dataGridColumns = new List<DataGridColumn>()
              {
                { new DataGridColumn("Path"){ColumnText="文件路径",Width=0,ColumnType=ColumnType.DefaultFilter}},
                { new DataGridColumn("Extension"){ColumnText="文件后缀",Width=-1}},
                { new DataGridColumn("Type"){ColumnText="类型",Width=150}},
                { new DataGridColumn("Length"){ColumnText="大小",Width=150}},
                { new DataGridColumn("Time"){ColumnText="时间",Width=150}},
              };


        public FolderWatcherForm()
        {
            InitializeComponent();
        }


        private void FileWatcherForm_Load(object sender,EventArgs e)
        {
            this.cboNotifyFilter.Nodes.Add(new TreeNode { Text = "创建",Tag = WatcherChangeTypes.Created,Checked = true });
            this.cboNotifyFilter.Nodes.Add(new TreeNode { Text = "重命名",Tag = WatcherChangeTypes.Renamed,Checked = true });
            this.cboNotifyFilter.Nodes.Add(new TreeNode { Text = "删除",Tag = WatcherChangeTypes.Deleted,Checked = true });
            this.cboNotifyFilter.Nodes.Add(new TreeNode { Text = "属性变更",Tag = WatcherChangeTypes.Changed,Checked = true });

            var changedNotifyFiltersNode = new TreeNode { Text = "属性变更选项" };
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "属性",Tag = "Attributes",Checked = true });
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "创建时间",Tag = "CreationTime",Checked = true });
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "目录名",Tag = "DirectoryName",Checked = true });
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "文件名",Tag = "FileName",Checked = true });
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "打开时间",Tag = "LastAccess",Checked = true });
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "写入时间",Tag = "LastWrite",Checked = true });
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "安全设置",Tag = "Security",Checked = true });
            changedNotifyFiltersNode.Nodes.Add(new TreeNode { Text = "大小",Tag = "Size",Checked = true });
            this.cboNotifyFilter.Nodes.Add(changedNotifyFiltersNode);
            changedNotifyFiltersNode.Expand();


            //初始化DataTable
            resultTable = new DataTable("ResultTable");
            resultTable.Columns.Add("Path",typeof(string));
            resultTable.Columns.Add("Extension",typeof(string));
            resultTable.Columns.Add("Type",typeof(string));
            resultTable.Columns.Add("Length",typeof(string));
            resultTable.Columns.Add("Time",typeof(string));

            this.dataDisplayControl.BindData(resultTable,this.dataGridColumns);

            this.uiToolTip.SetToolTip(this.lblFormatTag,"类似这样：*.txt|*.doc|*.jpg 或：*.xls 或：abc.txt");

            if(!string.IsNullOrEmpty(this.folderPath))
            {
                this.txtFolderPath.Text = this.folderPath;
                this.btnWatcher.PerformClick();//调用按钮的点击事件
            }

        }


        private void txtFolderPath_ButtonClick(object sender,EventArgs e)
        {
            string dir = txtFolderPath.Text;
            if(Dialogs.SelectDirEx("请选择需要监控的目录",ref dir))
            {
                this.txtFolderPath.Text = dir;
            }
        }

        private void btnWatcher_Click(object sender,EventArgs e)
        {
            if(this.btnWatcher.Text == "停止监控")
            {
                if(fileSystemWatcher == null || fileSystemWatcher.EnableRaisingEvents == false)
                {
                    this.ShowWarningNotifier("还未开始监控呢");
                    return;
                }
                this.fileSystemWatcher.EnableRaisingEvents = false;
                this.fileSystemWatcher.Dispose();
                this.fileSystemWatcher = null;
                this.btnWatcher.Text = "开始监控";
            }
            else if(this.btnWatcher.Text == "开始监控")
            {
                if(string.IsNullOrEmpty(this.txtFolderPath.Text))
                {
                    this.ShowWarningNotifier("请先选择需要监控的目录");
                    return;
                }

                var changedNotifyFiltersNode = this.cboNotifyFilter.Nodes.Cast<TreeNode>().First(it => it.Text == "属性变更选项");
                List<string> notifyFilters = new List<string>();
                foreach(TreeNode treeNode in changedNotifyFiltersNode.Nodes)
                {
                    if(treeNode.Checked)
                        notifyFilters.Add(treeNode.Tag.ToString());
                }
                if(notifyFilters.Count <= 0)
                {
                    this.ShowWarningNotifier("请至少选择一个【属性变更选项】");
                    return;
                }

                ClearResult();

                if(string.IsNullOrEmpty(this.txtExtensions.Text)) this.txtExtensions.Text = "*";

                FileWatcher(this.txtFolderPath.Text,this.txtExtensions.Text,notifyFilters);
                this.btnWatcher.Text = "停止监控";
            }
        }


        private bool NotifyFilterIsChecked(string text)
        {
            return this.cboNotifyFilter.Nodes.Cast<TreeNode>().FirstOrDefault(it => it.Checked == true && it.Text == text) != null;
        }


        private void FileWatcher(string path,string filter,List<string> notifyFilters)
        {
            this.fileSystemWatcher = new FileSystemWatcher(path)
            {
                //属性变更选项集合转为枚举
                NotifyFilter = (NotifyFilters)Enum.Parse(typeof(NotifyFilters),string.Join(",",notifyFilters)),

                //文件类型，支持通配符，“*.txt”只监视文本文件
                Filter = filter,    // 监控的文件格式
                IncludeSubdirectories = this.chbContainSubFolder.Checked  // 监控子目录
            };

            if(NotifyFilterIsChecked("属性变更"))
                this.fileSystemWatcher.Changed += new FileSystemEventHandler(OnChanged);
            if(NotifyFilterIsChecked("创建"))
                this.fileSystemWatcher.Created += new FileSystemEventHandler(OnCreated);
            if(NotifyFilterIsChecked("重命名"))
                this.fileSystemWatcher.Renamed += new RenamedEventHandler(OnRenamed);
            if(NotifyFilterIsChecked("删除"))
                this.fileSystemWatcher.Deleted += new FileSystemEventHandler(OnDeleted);
            fileSystemWatcher.Error += FileSystemWatcher_Error;
            //表示当前的路径正式开始被监控，一旦监控的路径出现变更，FileSystemWatcher 中的指定事件将会被触发。
            this.fileSystemWatcher.EnableRaisingEvents = true;
        }


        private void FileSystemWatcher_Error(object sender,ErrorEventArgs e)
        {
            SetResult("错误",ex: e.GetException());
        }

        private void OnCreated(object source,FileSystemEventArgs e)
        {
            SetResult("新增",e.FullPath,e.ChangeType);
        }

        private void OnChanged(object source,FileSystemEventArgs e)
        {
            SetResult($"属性变更",e.FullPath,e.ChangeType);
        }

        private void OnDeleted(object source,FileSystemEventArgs e)
        {
            SetResult($"删除",e.FullPath,e.ChangeType);
        }

        private void OnRenamed(object source,RenamedEventArgs e)
        {
            SetResult($"重命名",e.FullPath,e.ChangeType);
        }


        private void SetResult(string changeTypeStr,string path = null,WatcherChangeTypes changeType = WatcherChangeTypes.All,Exception ex = null)
        {
            DataRow dataRow = resultTable.NewRow();
            if(ex == null)
            {
                string type = GetPathTypeStr(path);

                string lengthStr = string.Empty;
                if(type == "文件")
                {
                    FileInfo fileInfo = new FileInfo(path);
                    if(fileInfo.Exists)
                        lengthStr = StorageHelper.FormatBytes(new FileInfo(path).Length);
                }

                string typeStr = GetPathTypeStr(path) + "：" + changeTypeStr;

                dataRow["Path"] = path;
                dataRow["Extension"] = type == "文件" ? Path.GetExtension(path) : string.Empty;
                dataRow["Type"] = typeStr;
                dataRow["Length"] = lengthStr;
                dataRow["Time"] = DateTime.Now;

                if(Setting.System.SendMsgModule.Contains("FileWatcher"))
                {
                    FeiShuMsgHelper.SendCardMsgAsync($"监控目录：{this.fileSystemWatcher?.Path.Replace(@"\","\\\\")}\\n路径：{path.Replace(@"\","\\\\")}\\n大小：{lengthStr}",$"目录监控-[{typeStr}]");
                }
            }
            else
            {
                dataRow["Path"] = ex.Message;
                dataRow["Extension"] = string.Empty;
                dataRow["Type"] = changeTypeStr;
                dataRow["Length"] = string.Empty;
                dataRow["Time"] = DateTime.Now;

                if(Setting.System.SendMsgModule.Contains("FileWatcher"))
                    FeiShuMsgHelper.SendCardMsgAsync($"监控目录【{this.fileSystemWatcher?.Path}】{ex.Message}",$"目录监控-异常",LogType.Error);
            }
            resultTable.Rows.Add(dataRow);

            try
            {
                this.Invoke(new Action(() =>
                {
                    int pageSize = this.txtPageSize.IntValue;
                    while(pageSize > 0 && resultTable.Rows.Count > pageSize)
                    {
                        resultTable.Rows.RemoveAt(0);  // 删除最早的数据
                    }

                    this.dataDisplayControl.BindData(resultTable,this.dataGridColumns);//显示结果


                }));
            }
            catch { }
        }


        private void btnClearDgv_Click(object sender,EventArgs e)
        {
            ClearResult();
        }

        private void ClearResult()
        {
            if(this.resultTable.Rows.Count > 0)
                this.resultTable.Clear();

            if(this.dataDisplayControl.DataGridView.Rows.Count > 0)
                this.dataDisplayControl.DataGridView.ClearAll();
        }


        private void dataDisplayControl_DataGridViewCellDoubleClick(DataGridViewEventArgs dataGridViewEventArgs)
        {
            if(dataGridViewEventArgs.MouseButton == MouseButtons.Left)//判断点的是不是左键
            {
                string path = dataGridViewEventArgs.Row.Cells["Path"].Value.ToString();
                string type = dataGridViewEventArgs.Row.Cells["Type"].Value.ToString();

                if(string.IsNullOrEmpty(path) || Path.IsPathRooted(path)) return;

                Process.Start(path);
            }
        }


        private string GetPathTypeStr(string path)
        {
            if(!string.IsNullOrEmpty(Path.GetExtension(path)))
            {
                return $"文件";
            }
            else if(string.IsNullOrEmpty(Path.GetExtension(path)) && File.Exists(path))
            {
                return $"文件";
            }
            else//目录
            {
                return "目录";
            }
        }


        private Color GetChangeTypeForeColor(WatcherChangeTypes changeType)
        {
            switch(changeType)
            {
                case WatcherChangeTypes.Created:
                    return Color.Green;
                case WatcherChangeTypes.Changed:
                    return Color.Blue;
                case WatcherChangeTypes.Renamed:
                    return Color.Purple;
                case WatcherChangeTypes.Deleted:
                    return Color.Orange;
                default: return Color.Red;
            }
        }


    }
}
